//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<time.h>
///	@path	~/src/utilities/
///	@date	2007/06/14
///	@desc	time definition in xeres.

#pragma once

#include "xeres.h"

#include <time.h>

namespace xeres {

	/// \brief Macro scale time.
	typedef clock_t TimeStamp;

	/// \brief Micro scale time,
	typedef int64 CounterStamp;

	/// \brief Real world time.
	typedef time_t DateTimeStamp;

	/// \brief Time partition.
	struct TimePartition
	{
		int nDay;
		int nHour;
		int nMinute;
		int nSecond;
		int nMilliSecond;
	};

	/// \brief Date time partition.
	struct DateTimePartition
	{
		int nYear;
		int nMonth;
		int nDay;
		int nHour;
		int nMinute;
		int nSecond;
		int nWeekday;
	};

	// forward declarations
	class Time;
	class Counter;
	class DateTime;


	/*!
		\class	Time
		\brief	Time representation.
		\details
			Time function encapsulation, a 'Time' saves time measurement,
			usually the standard time representation of system. <BR>
			Notice system calls accept Time as time representations,
			not Counter. But Counter can convert to Time.<BR>
			To represent time in real world, please use DateTime.

		\sa	Counter, DateTime
	*/
	class Time
	{
	public:

		/// \name Constructor
		//@{

		/// \ctor
		Time( void );

		/// \ctor_copy
		Time( const Time& rhs );

		/// \ctor_set
		Time( const TimeStamp& timeStamp );

		/// \ctor_set
		Time( const Time& start , const Time& end );

		//@}

		/// \name Time Manipulation
		//@{

		/*!
			\brief		Split time into readable structure.
		*/
		void PartitionTime( TimePartition& part ) const;

		/*!
			\brief		Convert time to milli-second.
		*/
		int64 ToMilliSecond( void ) const;

		/*!
			\brief		Convert time to milli-second.
		*/
		void ToMilliSecond( int64& m ) const;

		/*!
			\brief		Convert milli-second to time.
		*/
		void FromMilliSecond( int64 m );

		//@}

		/// \name Operators
		//@{

		/*!
			\brief		Assignment.
		*/
		Time& operator = ( const Time& rhs );

		/*!
			\brief		Assignment.
		*/
		Time& operator = ( const TimeStamp& timeStamp );

		/*!
			\brief		Addition.
		*/
		friend Time operator + ( const Time& lval , const Time& rhs );

		/*!
			\brief		Subtraction.
		*/
		friend Time operator - ( const Time& lval , const Time& rhs );

		/*!
			\brief		Comparison(time is longer or shorter).
		*/
		friend bool operator < ( const Time& lval , const Time& rhs );

		/*!
			\brief		Comparison(time is longer or shorter).
		*/
		friend bool operator > ( const Time& lval , const Time& rhs );

		/*!
			\brief		Comparison(2 times are the same?).
		*/
		friend bool operator == ( const Time& lval , const Time& rhs );

		/*!
			\brief		Comparison(2 times are different?).
		*/
		friend bool operator != ( const Time& lval , const Time& rhs );

		//@}

		/// \name Current Time
		//@{

		/*!
			\brief		Get current time.
		*/
		static Time Now( void );

		/*!
			\brief		Get current time.
		*/
		static void Now( Time& t );

		//@}

	private:

		TimeStamp			m_time;

	};

	/*!
		\class	Counter
		\brief	Counter function encapsulation.
		\details
			A Counter represent high resolution timing function.
			Differing Counter can get accurate bench mark such as
			FPS counting.<BR>
			Counter cannot represent real world time stamp.

		\sa	Time, DateTime
	*/
	class Counter
	{
	public:

		/// \name Constructor
		//@{

		/// \ctor
		Counter( void );

		/// \ctor_copy
		Counter( const Counter& rhs );

		/// \ctor_set
		Counter( const CounterStamp& counterStamp );

		/// \ctor_set
		Counter( const Counter& start , const Counter& end );

		//@}

		/// \name Counter Manipulation
		//@{

		/*!
			\brief		Convert counter to time.
		*/
		Time ToTime( void ) const;

		/*!
			\brief		Convert counter to time.
		*/
		void ToTime( Time& t ) const;

		/*! 
			\brief		Convert to second.
		*/
		long double ToSecond( void ) const;

		/*! 
			\brief		Convert to milli-second.
		*/
		double ToMilliSecond( void ) const;

		//@}

		/// \name Operators
		//@{

		/*!
			\brief		Assignment.
		*/
		Counter& operator = ( const Counter& rhs );

		/*!
			\brief		Assignment.
		*/
		Counter& operator = ( const CounterStamp& timeStamp );

		/*!
			\brief		Addition.
		*/
		friend Counter operator + ( const Counter& lval , const Counter& rhs );

		/*!
			\brief		Subtraction.
		*/
		friend Counter operator - ( const Counter& lval , const Counter& rhs );

		/*!
			\brief		Comparison(counter is larger or smaller).
		*/
		friend bool operator < ( const Counter& lval , const Counter& rhs );

		/*!
			\brief		Comparison(counter is larger or smaller).
		*/
		friend bool operator > ( const Counter& lval , const Counter& rhs );

		/*!
			\brief		Comparison(2 counters are the same?).
		*/
		friend bool operator == ( const Counter& lval , const Counter& rhs );

		/*!
			\brief		Comparison(2 counters are different?).
		*/
		friend bool operator != ( const Counter& lval , const Counter& rhs );

		//@}

		/// \name Current Counter
		//@{

		/*!
			\brief		Get current counter.
		*/
		static Counter Now( void );

		/*!
			\brief		Get current counter.
		*/
		static void Now( Counter& c );

		//@}

	private:

		CounterStamp		m_counter;

	};

	/*!
		\class	DateTime
		\brief	Date Time function encapsulation.
		\details
			DateTime is used to represent real world time.<BR>
			Different from Time, DateTime is strongly connect
			to 'real time'. Time represents measurement.

		\sa Time, Counter
	*/
	class DateTime
	{
	public:

		/// \name Constructor
		//@{

		/// \ctor
		DateTime( void );

		/// \ctor_copy
		DateTime( const DateTime& rhs );

		/// \ctor_set
		DateTime( const DateTimeStamp& dateTimeStamp );

		//@}

		/// \name DateTime Manipulation
		//@{

		/*!
			\brief		Determine if time is null.
		*/
		bool IsNull( void ) const;

		/*!
			\brief		Partition DateTime into readable structure.
		*/
		void PartitionDateTime( DateTimePartition& part ) const;

		/*!
			\brief		Make DateTime from readable structure.
		*/
		void FromPartition( const DateTimePartition& part );

		//@}

		/// \name Operators
		//@{

		/*!
			\brief		Assignment.
		*/
		DateTime& operator = ( const DateTime& rhs );

		/*!
			\brief		Assignment.
		*/
		DateTime& operator = ( const DateTimeStamp& timeStamp );

		/*!
			\brief		Comparison(2 date time are the same?).
		*/
		friend bool operator == ( const DateTime& lval , const DateTime& rhs );

		/*!
			\brief		Comparison(2 date time are different?).
		*/
		friend bool operator != ( const DateTime& lval , const DateTime& rhs );

		/*!
			\brief		Convert time stamp.
		*/
		operator DateTimeStamp ( void );

		//@}

		/// \name Current Date Time
		//@{

		/*!
			\brief		Get current counter.
		*/
		static DateTime Now( void );

		/*!
			\brief		Get current counter.
		*/
		static void Now( DateTime& t );

		//@}

	private:

		DateTimeStamp		m_time;

	};


} // namespace xeres

// all inlines
#include "lib/utilities/time.inl"
